package cn.ac.iie.di.ban.news.server.runtime;

import cn.ac.iie.di.ban.news.server.check.CheckDesc;
import cn.ac.iie.di.ban.news.server.config.Configuration;
import cn.ac.iie.di.ban.news.server.config.ConfigurationException;
import cn.ac.iie.di.datadock.rdata.exchange.client.core.REFieldType;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
/**
 *
 * @author zwlin
 */
public class RuntimeEnv {

    private static final Logger logger = Logger.getLogger(RuntimeEnv.class);

    /*server*/
    public static final String SERVER_PORT = "server.port";
    public static final String SERVER_PARALLEL = "server.parallel";
    public static final String SERVER_AUTH_TWO_WAY = "server.auth.twoway";

    public static final String HEARTBEAT_INTERVAL = "hearbeat.interval";
    public static final String CHECK_INTERVAL = "check.interval";
    public static final String DATA_CONFIG_HOSTS = "data.config.host";

    /*meta*/
    public static final String META_ACTIVATED = "meta.activated";
    public static final String META_KEYINFO_HOSTS = "meta.keyinfo.hosts";

    /*data*/
    public static final String DATA_ACTIVATED = "data.activated";
    public static final String DATA_HOST = "data.host";
    public static final String DATA_META_URLS = "data.meta.urls";
    public static final String DATA_TYPE = "data.type";//test or online

    //speed limiter
    public static final String DATA_SPEED_LIMIT_TOTAL_ACTIVATED = "data.speed.limit.total.activated";
    public static final String DATA_SPEED_LIMIT_TOTAL_TPS = "data.speed.limit.total.tps";
    public static final String DATA_SPEED_LIMIT_EACH_ACTIVATED = "data.speed.limit.each.activated";
    public static final String DATA_SPEED_LIMIT_EACH_TPS = "data.speed.limit.each.tps";
    public static final String DATA_SPEED_LIMIT_EACH_DETAIL = "data.speed.limit.each.detail";

    //file appender
    public static final String DATA_CACHE_DIR = "data.cache.dir";
    public static final String DATA_TARGET_DIR = "data.target.dir";

    //data trace
    //post data trace
    public static final String DATA_TRACE_URLS = "data.trace.urls";
    //rmq data trace
    public static final String DATA_TRACE_NAMESRV = "data.trace.namesrv";
    public static final String DATA_TRACE_TOPIC = "data.trace.topic";

    public static final String PUBLIC_OPINION_FILED = "public.opinion.filed";
    //checkers
    //types,int 1,2,3
    public static final String DATA_NEWS_TYPE = "data.news.type";
    public static final String DATA_NEWS_UPDATE_TYPE = "data.news.update.type";
    public static final String DATA_COMMENT_TYPE = "data.comment.type";
    public static final String DATA_COMMENT_UPDATE_TYPE = "data.comment.update.type";
    public static final String DATA_USER_TYPE = "data.user.type";

    //fields,map,  field0=int;[field1,string]{field2:Long};field4 string;(field3|int)
    public static final String DATA_NEWS_FIELDS = "data.news.fields";
    public static final String DATA_NEWS_UPDATE_FIELDS = "data.news.update.fields";
    public static final String DATA_COMMENT_FIELDS = "data.comment.fields";
    public static final String DATA_COMMENT_UPDATE_FIELDS = "data.comment.update.fields";
    public static final String DATA_USER_FIELDS = "data.user.fields";

    //required,strings
    public static final String DATA_NEWS_REQUIRED = "data.news.required";
    public static final String DATA_NEWS_UPDATE_REQUIRED = "data.news.update.required";
    public static final String DATA_COMMENT_REQUIRED = "data.comment.required";
    public static final String DATA_COMMENT_UPDATE_REQUIRED = "data.comment.update.required";
    public static final String DATA_USER_REQUIRED = "data.user.required";

    //check,map,with short present.
    public static final String DATA_NEWS_CHECK = "data.news.check";
    public static final String DATA_NEWS_UPDATE_CHECK = "data.news.update.check";
    public static final String DATA_COMMENT_CHECK = "data.comment.check";
    public static final String DATA_COMMENT_UPDATE_CHECK = "data.comment.update.check";
    public static final String DATA_USER_CHECK = "data.user.check";

    //nameesrv
    public static final String DATA_RMQ_NAMESRV = "data.rmq.namesrv";
    //topic
    public static final String DATA_NEWS_TOPIC = "data.news.topic";
    public static final String DATA_NEWS_UPDATE_TOPIC = "data.news.update.topic";
    public static final String DATA_COMMENT_TOPIC = "data.comment.topic";
    public static final String DATA_COMMENT_UPDATE_TOPIC = "data.comment.update.topic";
    public static final String DATA_USER_TOPIC = "data.user.topic";

    private static Configuration conf = null;
    public static HashMap<String, Object> dynamicParams = new HashMap<>();

    public static void init() throws RuntimeEnvException {
        conf = Configuration.getConfiguration(ClassLoader.getSystemClassLoader().getResource("configure.properties").getFile());
        getParamAsInteger(SERVER_PORT);
        getParamAsInteger(SERVER_PARALLEL);
        getParamAsBoolean(SERVER_AUTH_TWO_WAY, false);
        getParamAsInteger(HEARTBEAT_INTERVAL, 300);

        if (getParamAsBoolean(META_ACTIVATED, false)) {
            getParamAsStrings(META_KEYINFO_HOSTS);
        }
        if (getParamAsBoolean(DATA_ACTIVATED, false)) {

            getParamAsString(DATA_HOST);
            getParamAsStrings(DATA_META_URLS, new String[0]);
            getParamAsString(DATA_TYPE);

            //speed limiter
            if (getParamAsBoolean(DATA_SPEED_LIMIT_TOTAL_ACTIVATED, false)) {
                getParamAsInteger(DATA_SPEED_LIMIT_TOTAL_TPS);
            }
            if (getParamAsBoolean(DATA_SPEED_LIMIT_EACH_ACTIVATED, false)) {
                getParamAsInteger(DATA_SPEED_LIMIT_EACH_TPS, -1);
                getParamAsIntegerMap(DATA_SPEED_LIMIT_EACH_DETAIL, new HashMap<String, Integer>(0));
            }

            //file appender
            getParamAsString(DATA_CACHE_DIR, "");
            getParamAsString(DATA_TARGET_DIR, "");

            //data trace
            getParamAsStrings(DATA_TRACE_URLS, new String[0]);
            getParamAsString(DATA_TRACE_NAMESRV, "");
            getParamAsString(DATA_TRACE_TOPIC, "");

            //type
            getParamAsInteger(DATA_NEWS_TYPE);
            getParamAsInteger(DATA_NEWS_UPDATE_TYPE);
            getParamAsInteger(DATA_COMMENT_TYPE);
            getParamAsInteger(DATA_COMMENT_UPDATE_TYPE);
            getParamAsInteger(DATA_USER_TYPE);

            //fields
            getParamAsMap(DATA_NEWS_FIELDS);
            getParamAsMap(DATA_NEWS_UPDATE_FIELDS);
            getParamAsMap(DATA_COMMENT_FIELDS);
            getParamAsMap(DATA_COMMENT_UPDATE_FIELDS);
            getParamAsMap(DATA_USER_FIELDS);

            //required
            getParamAsStrings(DATA_NEWS_REQUIRED);
            getParamAsStrings(DATA_NEWS_UPDATE_REQUIRED);
            getParamAsStrings(DATA_COMMENT_REQUIRED);
            getParamAsStrings(DATA_COMMENT_UPDATE_REQUIRED);
            getParamAsStrings(DATA_USER_REQUIRED);

            //check
            getParamAsMap(DATA_NEWS_CHECK);
            getParamAsMap(DATA_NEWS_UPDATE_CHECK);
            getParamAsMap(DATA_COMMENT_CHECK);
            getParamAsMap(DATA_COMMENT_UPDATE_CHECK);
            getParamAsMap(DATA_USER_CHECK);

            //rocketmq 
            if (!getParamAsString(DATA_RMQ_NAMESRV, "").isEmpty()) {
                getParamAsString(DATA_NEWS_TOPIC);
                getParamAsString(DATA_NEWS_UPDATE_TOPIC);
                getParamAsString(DATA_COMMENT_TOPIC);
                getParamAsString(DATA_COMMENT_UPDATE_TOPIC);
                getParamAsString(DATA_USER_TOPIC);
            }
        }

    }

    public static String getParamAsString(String param) throws RuntimeEnvException {
        if (conf == null) {
            throw new RuntimeEnvException("conf not inited. Please call RuntimeEnv.init() first!");
        }
        String val = dynamicParams.get(param)+"";
        if (val == null || "null".equals(val.toLowerCase())) {
            val = conf.getString(param, null);
            if (val == null) {
                throw new RuntimeEnvException("param " + param + " not set!");
            }
            dynamicParams.put(param, val);
        }
        return val;
    }

    public static String getParamAsString(String param, String Default) throws RuntimeEnvException {
        if (conf == null) {
            throw new RuntimeEnvException("conf not inited. Please call RuntimeEnv.init() first!");
        }
        String val = (String) dynamicParams.get(param);
        if (val == null) {
            val = conf.getString(param, Default);
            dynamicParams.put(param, val);
        }
        return val;
    }

    public static String[] getParamAsStrings(String param) throws RuntimeEnvException {
        if (conf == null) {
            throw new RuntimeEnvException("conf not inited. Please call RuntimeEnv.init() first!");
        }
        String[] val = (String[]) dynamicParams.get(param);
        if (val == null) {
            val = conf.getStrings(param, null);
            if (val == null) {
                throw new RuntimeEnvException("param " + param + " not set!");
            }
            dynamicParams.put(param, val);
        }
        return val;
    }

    public static String[] getParamAsStrings(String param, String[] Default) throws RuntimeEnvException {
        if (conf == null) {
            throw new RuntimeEnvException("conf not inited. Please call RuntimeEnv.init() first!");
        }
        String[] val = (String[]) dynamicParams.get(param);
        if (val == null) {
            val = conf.getStrings(param, Default);
            dynamicParams.put(param, val);
        }
        return val;
    }

    public static Map<String, REFieldType> getParamAsTypeMap(String param) throws RuntimeEnvException {
        Map<String, String> srcMap = getParamAsMap(param);
        HashMap<String, REFieldType> rtn = new HashMap<>();
        for (Map.Entry<String, String> entry : srcMap.entrySet()) {
            switch (entry.getValue().trim().toLowerCase()) {
                case "int":
                case "integer":
                case "n":
                case "i":
                case "\\d":
                case "int_s":
                    rtn.put(entry.getKey(), REFieldType.Int);
                    break;
                case "long":
                case "l":
                case "ld":
                case "long_s":
                    rtn.put(entry.getKey(), REFieldType.Long);
                    break;
                case "string":
                case "str":
                case "s":
                case "\\s":
                case "string_s":
                    rtn.put(entry.getKey(), REFieldType.String);
                    break;
                case "strings":
                case "string[]":
                case "array<string>":
                case "string_a":
                    rtn.put(entry.getKey(), REFieldType.Strings);
                    break;
            }
        }
        return rtn;
    }

    public static Map<String, CheckDesc> getParamAsCheckDescMap(String param) throws RuntimeEnvException {
        Map<String, String> srcMap = getParamAsMap(param);
        HashMap<String, CheckDesc> rtn = new HashMap<>();
        for (Map.Entry<String, String> entry : srcMap.entrySet()) {
            CheckDesc desc = CheckDesc.parse(entry.getValue());
            if (desc != null) {
                rtn.put(entry.getKey(), desc);
            }
        }
        return rtn;
    }

    public static Map<String, Integer> getParamAsIntegerMap(String param) throws RuntimeEnvException {
        Map<String, String> srcMap = getParamAsMap(param);
        HashMap<String, Integer> rtn = new HashMap<>();
        for (Map.Entry<String, String> entry : srcMap.entrySet()) {
            int v = Integer.parseInt(entry.getValue());

            rtn.put(entry.getKey(), v);
        }
        return rtn;
    }

    public static Map<String, Integer> getParamAsIntegerMap(String param, Map<String, Integer> Default) throws RuntimeEnvException {
        HashMap<String, String> obj = new HashMap<>();
        Map<String, String> srcMap = getParamAsMap(param, obj);
        if (srcMap == obj) {
            return Default;
        }
        HashMap<String, Integer> rtn = new HashMap<>();
        for (Map.Entry<String, String> entry : srcMap.entrySet()) {
            int v = Integer.parseInt(entry.getValue());
            rtn.put(entry.getKey(), v);
        }
        return rtn;
    }

    public static Map<String, String> getParamAsMap(String param) throws RuntimeEnvException {
        if (conf == null) {
            throw new RuntimeEnvException("conf not inited. Please call RuntimeEnv.init() first!");
        }
        Map<String, String> val = (Map<String, String>) dynamicParams.get(param);
        if (val == null) {
            try {
                val = conf.getMap(param, null);
            } catch (ConfigurationException ex) {
                throw new RuntimeEnvException("get runtime env error with map value! param = " + param, ex);
            }
            if (val == null) {
                throw new RuntimeEnvException("param " + param + " not set!");
            }
            dynamicParams.put(param, val);
        }
        return val;
    }

    public static Map<String, String> getParamAsMap(String param, Map<String, String> Default) throws RuntimeEnvException {
        if (conf == null) {
            throw new RuntimeEnvException("conf not inited. Please call RuntimeEnv.init() first!");
        }
        Map<String, String> val = (Map<String, String>) dynamicParams.get(param);
        if (val == null) {
            try {
                val = conf.getMap(param, Default);
            } catch (ConfigurationException ex) {
                throw new RuntimeEnvException("get runtime env error with map value! param = " + param, ex);
            }
            dynamicParams.put(param, val);
        }
        return val;
    }

    public static Integer getParamAsInteger(String param) throws RuntimeEnvException {
        Integer val = (Integer) dynamicParams.get(param);
        if (val == null) {
            try {
                val = conf.getInt(param, -1);
            } catch (ConfigurationException ex) {
                throw new RuntimeEnvException("get runtime env error with integer value! param = " + param, ex);
            }
            if (val == -1) {
                throw new RuntimeEnvException("param " + param + " not set!");
            }
            dynamicParams.put(param, val);
        }
        return val;
    }

    public static Integer getParamAsInteger(String param, Integer Default) throws RuntimeEnvException {
        Integer val = (Integer) dynamicParams.get(param);
        if (val == null) {
            try {
                val = conf.getInt(param, Default);
            } catch (ConfigurationException ex) {
                throw new RuntimeEnvException("get runtime env error with integer value! param = " + param, ex);
            }
            dynamicParams.put(param, val);
        }
        return val;
    }

    public static boolean getParamAsBoolean(String param) throws RuntimeEnvException {
        Boolean val = (Boolean) dynamicParams.get(param);
        if (val == null) {
            try {
                val = conf.getBoolean(param, null);
            } catch (ConfigurationException ex) {
                throw new RuntimeEnvException("get runtime env error with boolean value! param = " + param, ex);
            }
            if (val == null) {
                throw new RuntimeEnvException("param " + param + " not set!");
            }
            dynamicParams.put(param, val);
        }
        return val;
    }

    public static boolean getParamAsBoolean(String param, Boolean Default) throws RuntimeEnvException {
        Boolean val = (Boolean) dynamicParams.get(param);
        if (val == null) {
            try {
                val = conf.getBoolean(param, Default);
            } catch (ConfigurationException ex) {
                throw new RuntimeEnvException("get runtime env error with boolean value! param = " + param, ex);
            }
            dynamicParams.put(param, val);
        }
        return val;
    }

}
